/*
 * Copyright (C) 2016, apexes.net. All rights reserved.
 * 
 *        http://www.apexes.net
 * 
 */
package net.apexes.wsonrpc.server.support;

import net.apexes.wsonrpc.core.JsonRpcEngine;
import net.apexes.wsonrpc.core.ServiceRegistry;
import net.apexes.wsonrpc.core.Transport;
import net.apexes.wsonrpc.core.exception.WsonrpcException;
import net.apexes.wsonrpc.json.JsonImplementor;
import net.apexes.wsonrpc.json.support.gson.GsonImplementor;
import net.apexes.wsonrpc.server.support.http.NanoHTTPD;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 *
 */
public class HttpJsonRpcServer extends NanoHTTPD {
    
    private final JsonRpcEngine jsonRpcEngine;
    
    public HttpJsonRpcServer(int port) {
        this(port, new GsonImplementor());
    }

    public HttpJsonRpcServer(int port, JsonImplementor jsonImpl) {
        super(port);
        jsonRpcEngine = new JsonRpcEngine(jsonImpl);
    }
    
    public ServiceRegistry getServiceRegistry() {
        return jsonRpcEngine.getServiceRegistry();
    }

    @Override
    public Response serve(IHTTPSession session) {
        Map<String, String> files = new HashMap<>();
        Method method = session.getMethod();
        if (Method.POST.equals(method)) {
            try {
                session.parseBody(files);
                String json = files.get("postData");
                TransportImpl transport = new TransportImpl();
                jsonRpcEngine.receiveRequest(json.getBytes(StandardCharsets.UTF_8), transport);
                return newFixedLengthResponse(transport.json);
            } catch (IOException e) {
                return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT,
                        "SERVER INTERNAL ERROR: IOException: " + e.getMessage());
            } catch (WsonrpcException e) {
                return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT,
                        "SERVER INTERNAL ERROR: WsonrpcException: " + e.getMessage());
            } catch (ResponseException e) {
                return newFixedLengthResponse(e.getStatus(), NanoHTTPD.MIME_PLAINTEXT, e.getMessage());
            }
        }
        return super.serve(session);
    }

    /**
     * 
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     *
     */
    private static class TransportImpl implements Transport {

        private String json;

        @Override
        public void sendBinary(byte[] bytes) throws IOException {
            this.json = new String(bytes, StandardCharsets.UTF_8);
        }

    }
    
}
